import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import AlipaySdk from 'alipay-sdk';
import {
  Alipay_CreatePay_SeClass,
  Alipay_PayCallBack_SeClass,
  Alipay_Refund_SeClass,
} from './assets/alipay.class';

@Injectable()
export class Alipay_Service {
  private alipayClient: AlipaySdk;
  constructor(private configService: ConfigService) {
    this.alipayClient = new AlipaySdk({
      // 支付宝分配给开发者的应用ID
      appId: this.configService.get<string>('ALIPAY_APPID'),
      privateKey: this.configService.get<string>('ALIPAY_PRIVATEKEY'),
      alipayPublicKey: this.configService.get<string>('ALIPAY_PUBLICKEY'),
      gateway: 'https://openapi.alipay.com/gateway.do',
      timeout: 5000,
      charset: 'utf-8',
      signType: 'RSA2',
    });
  }

  /**
   * @description
   * 该方法用于创建支付宝支付请求，生成用户在支付宝页面上支付的链接。
   * 使用支付宝客户端的 `pageExec` 方法，调用 `alipay.trade.wap.pay` 接口。
   * @example
   * const order = new Order();
   * const result = await this.alipay_CreatePay(order);
   * @param {Order} body - 订单记录对象，包含订单的详细信息。
   * @returns {string} - 返回支付宝支付请求的结果。
   * @throws {Error} - 如果支付宝支付请求失败，将抛出错误。
   */
  alipay_CreatePay(body: Alipay_CreatePay_SeClass): string {
    console.log(body.outTradeNo, 99);
    return this.alipayClient.pageExec('alipay.trade.wap.pay', {
      bizContent: {
        outTradeNo: body.outTradeNo, //商户网站唯一订单号 必传
        productCode: 'QUICK_WAP_WAY', //销售产品码，商家和支付宝签约的产品码。手机网站支付为：QUICK_WAP_WAY  必传
        totalAmount: body.totalAmount, //订单总金额。单位为元，精确到小数点后两位，取值范围：[0.01,100000000]。 必传
        subject: body.subject, //订单标题。注意：不可使用特殊字符，如 /，=，& 等。必传
        //公用回传参数，如果请求时传递了该参数，则返回给商户时会回传该参数。支付宝只会在同步返回（包括跳转回商户网站）和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。
        passback_params: encodeURIComponent(body.passback_params),
      },
      // 支付宝服务器主动通知商户服务器里指定的页面http/https路径。  可选
      notify_url:
        this.configService.get<string>('SERVICE_HOST') +
        this.configService.get<string>('ALIPAY_CALLBACK'),
    });
  }

  alipay_PayCallBack(body: Alipay_PayCallBack_SeClass): 'fail' | 'success' {
    const isVerified = this.alipayClient.checkNotifySign(body);
    const isVerifiedd = body.trade_status === 'TRADE_SUCCESS' || body.trade_status === 'TRADE_FINISHED';
    if (!isVerified || !isVerifiedd) return 'fail';
    return 'success';
  }

  async alipay_Refund(body: Alipay_Refund_SeClass): Promise<string> {
    const result = await this.alipayClient.exec('alipay.trade.refund', {
      bizContent: {
        out_trade_no: body.out_trade_no, // 和trade_nostring(64)二选一
        // 必选price(16) 退款金额。 需要退款的金额，该金额不能大于订单金额，单位为元，支持两位小数。 注：如果正向交易使用了营销，该退款金额包含营销金额，支付宝会按业务规则分配营销和买家自有资金分别退多少，默认优先退买家的自有资金。如交易总金额100元，用户支付时使用了80元自有资金和20元无资金流的营销券，商家实际收款80元。如果首次请求退款60元，则60元全部从商家收款资金扣除退回给用户自有资产；如果再请求退款40元，则从商家收款资金扣除20元退回用户资产以及把20元的营销券退回给用户（券是否可再使用取决于券的规则配置）。
        refund_amount: body.refund_amount,
      },
    });
    if (result.code === '10000') return 'success';
    return result.sub_msg; // 业务返回码描述 string
  }

  async alipayCancel(data: { out_trade_no: string }): Promise<string> {
    try {
      console.log(data.out_trade_no, 199);
      const result = await this.alipayClient.exec('alipay.trade.close', {
        bizContent: {
          outTradeNo: data.out_trade_no, // 和trade_no string(64)二选一
        },
      });
      console.log(result);

      if (result.code == String(10000)) return 'success';
    } catch (error) {
      return error.message;
    }
  }
}
